#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdint.h>
#include <iostream>
#include <atomic>
#include <emmintrin.h> // 用于_mm_pause指令
#include <errno.h>
#include <string.h>

#include "l1_msg.h"

// 线程函数：读取共享数据
void* reader_thread(void* arg) {
  ThreadArgs* args = (ThreadArgs*)arg;
  SharedData* shm = args->shm;
  // 将当前线程绑定到指定的CPU核心
  // 为了实现最低延迟的线程间通信，应将读写线程绑定到同一物理核心的两个逻辑核心（超线程）
  // 这样它们可以共享L1缓存，减少跨核同步开销
  cpupin(args->cpu_id);
  uint64_t total_latency_cycles = 0;
  int mismatch_count = 0;
  int received_messages = 0;

  // 从共享内存读取数据（直接从L1缓存获取）
  for (int i = 0; i < MSG_COUNT; i++) {
    // 等待数据就绪
    while (shm->flag.load(std::memory_order_acquire) == 0) {
      _mm_pause(); // 减少CPU功耗，提示处理器其他线程可以使用超线程资源
    }
    std::atomic_thread_fence(std::memory_order_acquire); // 内存屏障确保数据读取正确
    uint64_t span_cycles = rdtscp() - shm->time_cycles;  // 使用CPU周期计数计算延迟
    total_latency_cycles += span_cycles;
    received_messages++;
    
    if (i != shm->seq_id) {
      mismatch_count++;
    }
    shm->flag.store(0, std::memory_order_release);  // 通知写入方已读取
  }

  if (received_messages > 0) {
    double avg_cycles = static_cast<double>(total_latency_cycles) / received_messages;
    double avg_nanoseconds = cycles_to_nanoseconds(avg_cycles);
    double avg_microseconds = cycles_to_microseconds(avg_cycles);

    std::cout << "CPU Frequency: " << get_cpu_frequency() << " GHz" << std::endl;
    std::cout << "Average latency over " << received_messages << " messages: " 
              << avg_cycles << " CPU cycles" << std::endl;
    std::cout << "Average latency: " << avg_nanoseconds << " ns" << std::endl;
    std::cout << "Average latency: " << avg_microseconds << " μs" << std::endl;
    
    if (mismatch_count > 0) {
      std::cout << "Sequence mismatches: " << mismatch_count << std::endl;
    }
  } else {
    std::cout << "No messages received" << std::endl;
  }
  
  return NULL;
}

int main(int argc, char** argv) {
  // 检查命令行参数数量
  if (argc < 2) {
    std::cerr << "Usage: " << argv[0] << " <reader_cpu_id>" << std::endl;
    std::cerr << "Example: " << argv[0] << " 9  # Binds thread to specific CPU core" << std::endl;
    return 1;
  }

  // 创建或打开一个命名共享内存对象
  int fd = shm_open("/cross_proc_shm", O_CREAT | O_RDWR, 0666);
  if (fd == -1) {
    std::cerr << "shm_open (reader) failed: " << strerror(errno) << std::endl;
    return 1;
  }

  // 设置共享内存大小（确保与写入进程一致）
  if (ftruncate(fd, sizeof(SharedData)) == -1) {
    std::cerr << "ftruncate (reader) failed: " << strerror(errno) << std::endl;
    close(fd);
    shm_unlink("/cross_proc_shm");
    return 1;
  }

  // 将共享内存映射到当前进程地址空间
  SharedData* shm = (SharedData*)mmap(NULL, sizeof(SharedData),
                                      PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if (shm == MAP_FAILED) {
    std::cerr << "mmap (reader) failed: " << strerror(errno) << std::endl;
    close(fd);
    shm_unlink("/cross_proc_shm");
    return 1;
  }

  // 验证映射的内存是否有效
  if (shm == nullptr) {
    std::cerr << "Failed to map shared memory" << std::endl;
    munmap(shm, sizeof(SharedData));
    close(fd);
    shm_unlink("/cross_proc_shm");
    return 1;
  }

  // 初始化同步标志为未就绪状态，确保writer启动时看到正确的初始状态
  shm->flag.store(0, std::memory_order_release);

  // 创建线程参数，接收用户指定的CPU ID
  ThreadArgs reader_args = {shm, atoi(argv[1])};

  // 创建读线程
  pthread_t reader;
  if (pthread_create(&reader, NULL, reader_thread, &reader_args) != 0) {
    std::cerr << "Failed to create reader thread" << std::endl;
    munmap(shm, sizeof(SharedData));
    close(fd);
    shm_unlink("/cross_proc_shm");
    return 1;
  }

  pthread_join(reader, NULL);

  // 清理资源
  munmap(shm, sizeof(SharedData));  // 解除内存映射
  close(fd);
  // 读取进程负责清理共享内存对象
  shm_unlink("/cross_proc_shm");

  return 0;
}